/*
 * Copyright 2010 - 2011, The PLDesktop Development Team
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#ifndef PLPROCESS_THREAD_H
#define PLPROCESS_THREAD_H

#include <stddef.h>
#include <machine/pc/processor/processor.h>

class PLProcess;

#define STACKSIZE 4096

/**
 * A thread of the application or a subthread of another thread.
 */
class PLThread {
public:
	/**
	 * Constructor.
	 *
	 * @param process The process of the thread if the thread was created
	 * from the process.
	 */
	PLThread(PLProcess *process);
	/**
	 * Constructor.
	 *
	 * @param process The process of the thread.
	 * @param parent The parent thread that creates this thread.
	 */
	PLThread(PLProcess *process, PLThread *parent);
	/**
	 * Init all values for the thread and create a new virtual memory management
	 * table.
	 */
	void init();
	/**
	 * Reset the thread instance to use it for another thread so we must not delete
	 * so many thread instances.
	 */
	void clear();
	/**
	 * Set the process for the thread.
	 *
	 * @param process The process to set.
	 */
	inline void setProcessFromThread(PLProcess *process);
	/**
	 * Get the process of the thread.
	 *
	 * @return The process.
	 */
	inline const PLProcess *process();
	/**
	 * Set the parent thread of this thread.
	 *
	 * @param thread The parent thread to set.
	 */
	inline void setParentThread(PLThread *thread);
	/**
	 * Get the parent thread of this thread.
	 *
	 * @return The parent thread.
	 */
	inline const PLThread *parent();
	/**
	 * Create a new thread and register it to the process.
	 *
	 * @return The thread that was created.
	 */
	PLThread *createThread();
private:
	void clearState();
	void threadEntry();
	PLProcess *m_process;
	PLThread *m_parentThread;
	uint8_t m_stack[STACKSIZE];
	uint32_t m_id;
	char *m_name;
	InterruptState *m_state;
};

void PLThread::setProcessFromThread(PLProcess *_process) {
	m_process = _process;
}

const PLProcess *PLThread::process() {
	return m_process;
}

void PLThread::setParentThread(PLThread *_thread) {
	m_parentThread = _thread;
}

const PLThread *PLThread::parent() {
	return m_parentThread;
}

#endif
